﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DJY.Code.Net
{
    public class Zcy_Sign
    {
        public static string CA_HEADER_PREFIX = "X-Ca-";

        /// <summary>
        /// 构建待签名字符串
        /// </summary>
        /// <param name="uri">服务器请求URL</param>
        /// <param name="headers">请求头</param>
        /// <param name="param">参数</param>
        /// <param name="method">方法：POST,GET</param>
        /// <returns></returns>
        public static string buildStringToSign(string uri,
            Dictionary<string, string> headers,
            Dictionary<string, object> param,
            string method)
        {
            char lf = '\n';
            StringBuilder sb = new StringBuilder();
            sb.Append(method).Append(lf);
            if (headers.ContainsKey("Accept"))
            {
                sb.Append(headers["Accept"]);
            }
            sb.Append(lf);
            if (headers.ContainsKey("Content-MD5"))
            {
                sb.Append(headers["Content-MD5"]);
            }
            sb.Append(lf);
            if (headers.ContainsKey("Content-Type"))
            {
                sb.Append(headers["Content-Type"]);
            }
            sb.Append(lf);
            if (headers.ContainsKey("Date"))
            {
                sb.Append(headers["Date"]);
            }
            sb.Append(lf);
            sb.Append(buildHeaders(headers));
            sb.Append(buildResource(uri, param));
            return sb.ToString();
        }

        /**
         * 组装Path+Param
         * 
         * @param uri
         * @param param
         * @return
         */

        private static string buildResource(string uri, Dictionary<string, object> param)
        {
            if (uri.Contains("?"))
            {
                string path = uri.Split('?')[0];
                string queryString = uri.Split('?')[1];

                uri = path;

                if (param == null)
                {
                    param = new Dictionary<string, object>();
                }

                if (queryString != null && queryString != "")
                {

                    foreach (string query in queryString.Split('&'))
                    {
                        string key = query.Split('=')[0];
                        string value = query.Split('=')[1];
                        if (!param.ContainsKey(key))
                        {
                            param.Add(key, value);
                        }
                    }
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.Append(uri);
            if (param != null && param.Count > 0)
            {
                sb.Append('?');

                //参数Key按字典排序
                //Dictionary<string, object> sortMap = new Dictionary<string, object>();
                //sortMap.pitall(param);
                param.OrderBy(s => s.Key);

                int flag = 0;

                var dicSort = from objDic in param orderby objDic.Key ascending select objDic;

                foreach (KeyValuePair<string, object> e in dicSort)
                {
                    if (flag != 0)
                    {
                        sb.Append('&');
                    }
                    flag++;

                    // value可能是list也可能是string
                    string key = e.Key;
                    object val = e.Value;
                    if (val == null || val.ToString() == "")
                    {
                        sb.Append(key);
                    }
                    else
                    {
                        if (val is Array)
                        {
                            List<string> l = (List<string>)val;
                            if (l.Count == 0)
                            {
                                sb.Append(key);
                            }
                            else
                            {
                                sb.Append(key).Append("=").Append(l[0]);
                            }
                        }
                        else
                        {
                            sb.Append(key).Append("=").Append((string)val);
                        }
                    }
                }
            }
            return sb.ToString();
        }

        /**
         * 组装Header
         * 
         * @param headers
         * @return
         */
        private static string buildHeaders(Dictionary<string, string> headers)
        {

            Dictionary<string, string> headersToSign = new Dictionary<string, string>();

            if (headers != null)
            {
                StringBuilder signHeadersStringBuilder = new StringBuilder();

                int flag = 0;
                foreach (var header in headers)
                {

                    if (header.Key.StartsWith(CA_HEADER_PREFIX))
                    {
                        if (flag != 0)
                        {
                            signHeadersStringBuilder.Append(",");
                        }
                        flag++;
                        signHeadersStringBuilder.Append(header.Key);
                        headersToSign.Add(header.Key, header.Value);
                    }
                }
                headers.Add("X-Ca-Signature-Headers", signHeadersStringBuilder.ToString());
            }

            StringBuilder sb = new StringBuilder();

            var dicSort = from objDic in headersToSign orderby objDic.Key ascending select objDic;
            foreach (KeyValuePair<string, string> kvp in dicSort)
            {
                sb.Append(kvp.Key).Append(':').Append(kvp.Value).Append('\n');
            }

            return sb.ToString();
        }
    }
}
